// Decompiled on 周六 2月 22 19:31:49 CST 2025 with Zomboid Decompiler v0.1.3 using Vineflower.
package zombie.popman;

import java.nio.ByteBuffer;
import java.util.LinkedList;
import zombie.ai.State;
import zombie.ai.states.ZombieEatBodyState;
import zombie.ai.states.ZombieIdleState;
import zombie.ai.states.ZombieSittingState;
import zombie.ai.states.ZombieTurnAlerted;
import zombie.characters.IsoPlayer;
import zombie.characters.IsoZombie;
import zombie.core.Core;
import zombie.core.raknet.UdpConnection;
import zombie.debug.DebugLog;
import zombie.debug.DebugType;
import zombie.iso.IsoChunkMap;
import zombie.iso.IsoGridSquare;
import zombie.iso.IsoMovingObject;
import zombie.iso.IsoUtils;
import zombie.iso.IsoWorld;
import zombie.network.GameServer;
import zombie.util.Type;

public class NetworkZombieManager {
    private static final NetworkZombieManager instance = new NetworkZombieManager();
    private final NetworkZombieList owns = new NetworkZombieList();
    private static final float NospottedDistanceSquared = 16.0F;

    public static NetworkZombieManager getInstance() {
        return instance;
    }

    public int getAuthorizedZombieCount(UdpConnection con) {
        return (int)IsoWorld.instance.CurrentCell.getZombieList().stream().filter(isoZombie -> isoZombie.authOwner == con).count();
    }

    public int getUnauthorizedZombieCount() {
        return (int)IsoWorld.instance.CurrentCell.getZombieList().stream().filter(isoZombie -> isoZombie.authOwner == null).count();
    }

    public static boolean canSpotted(IsoZombie zombie) {
        if (zombie.isRemoteZombie()) {
            return false;
        } else if (zombie.target != null && IsoUtils.DistanceToSquared(zombie.x, zombie.y, zombie.target.x, zombie.target.y) < 16.0F) {
            return false;
        } else {
            State state = zombie.getCurrentState();
            return state == null
                || state == ZombieIdleState.instance()
                || state == ZombieEatBodyState.instance()
                || state == ZombieSittingState.instance()
                || state == ZombieTurnAlerted.instance();
        }
    }

    public void updateAuth(IsoZombie zombie) {
        if (GameServer.bServer) {
            if (System.currentTimeMillis() - zombie.lastChangeOwner >= 2000L || zombie.authOwner == null) {
                if (zombie.SystemDisabler.zombiesSwitchOwnershipEachUpdate && GameServer.getPlayerCount() > 1) {
                    if (zombie.authOwner == null) {
                        for (int int0 = 0; int0 < GameServer.udpEngine.connections.size(); int0++) {
                            UdpConnection udpConnection0 = (UdpConnection)GameServer.udpEngine.connections.get(int0);
                            if (udpConnection0 != null) {
                                this.moveZombie(zombie, udpConnection0, null);
                                break;
                            }
                        }
                    } else {
                        int int1 = GameServer.udpEngine.connections.indexOf(zombie.authOwner) + 1;

                        for (int int2 = 0; int2 < GameServer.udpEngine.connections.size(); int2++) {
                            UdpConnection udpConnection1 = (UdpConnection)GameServer.udpEngine
                                .connections
                                .get((int2 + int1) % GameServer.udpEngine.connections.size());
                            if (udpConnection1 != null) {
                                this.moveZombie(zombie, udpConnection1, null);
                                break;
                            }
                        }
                    }
                } else {
                    if (zombie.target instanceof IsoPlayer) {
                        UdpConnection udpConnection2 = GameServer.getConnectionFromPlayer((IsoPlayer)zombie.target);
                        if (udpConnection2 != null && udpConnection2.isFullyConnected()) {
                            float float0 = ((IsoPlayer)zombie.target).getRelevantAndDistance(zombie.x, zombie.y, (float)(udpConnection2.ReleventRange - 2));
                            if (!Float.isInfinite(float0)) {
                                this.moveZombie(zombie, udpConnection2, (IsoPlayer)zombie.target);
                                if (Core.bDebug) {
                                    DebugLog.log(
                                        DebugType.Ownership,
                                        String.format(
                                            "Zombie (%d) owner (\"%s\"): zombie has target", zombie.getOnlineID(), ((IsoPlayer)zombie.target).getUsername()
                                        )
                                    );
                                }

                                return;
                            }
                        }
                    }

                    UdpConnection udpConnection3 = zombie.authOwner;
                    IsoPlayer isoPlayer0 = zombie.authOwnerPlayer;
                    float float1 = Float.POSITIVE_INFINITY;
                    if (udpConnection3 != null) {
                        float1 = udpConnection3.getRelevantAndDistance(zombie.x, zombie.y, zombie.z);
                    }

                    for (int int3 = 0; int3 < GameServer.udpEngine.connections.size(); int3++) {
                        UdpConnection udpConnection4 = (UdpConnection)GameServer.udpEngine.connections.get(int3);
                        if (udpConnection4 != udpConnection3) {
                            for (IsoPlayer isoPlayer1 : udpConnection4.players) {
                                if (isoPlayer1 != null && isoPlayer1.isAlive()) {
                                    float float2 = isoPlayer1.getRelevantAndDistance(zombie.x, zombie.y, (float)(udpConnection4.ReleventRange - 2));
                                    if (!Float.isInfinite(float2) && (udpConnection3 == null || float1 > float2 * 1.618034F)) {
                                        udpConnection3 = udpConnection4;
                                        float1 = float2;
                                        isoPlayer0 = isoPlayer1;
                                    }
                                }
                            }
                        }
                    }

                    if (Core.bDebug && isoPlayer0 != null && isoPlayer0 != zombie.authOwnerPlayer) {
                        DebugLog.log(
                            DebugType.Ownership, String.format("Zombie (%d) owner (\"%s\"): zombie is closer", zombie.getOnlineID(), isoPlayer0.getUsername())
                        );
                    }

                    if (udpConnection3 == null && zombie.isReanimatedPlayer()) {
                        for (int int4 = 0; int4 < GameServer.udpEngine.connections.size(); int4++) {
                            UdpConnection udpConnection5 = (UdpConnection)GameServer.udpEngine.connections.get(int4);
                            if (udpConnection5 != udpConnection3) {
                                for (IsoPlayer isoPlayer2 : udpConnection5.players) {
                                    if (isoPlayer2 != null && isoPlayer2.isDead() && isoPlayer2.ReanimatedCorpse == zombie) {
                                        udpConnection3 = udpConnection5;
                                        isoPlayer0 = isoPlayer2;
                                        if (Core.bDebug) {
                                            DebugLog.log(
                                                DebugType.Ownership,
                                                String.format(
                                                    "Zombie (%d) owner (\"%s\"): zombie is reanimated", zombie.getOnlineID(), isoPlayer2.getUsername()
                                                )
                                            );
                                        }
                                    }
                                }
                            }
                        }
                    }

                    if (udpConnection3 != null && !udpConnection3.RelevantTo(zombie.x, zombie.y, (float)((udpConnection3.ReleventRange - 2) * 10))) {
                        udpConnection3 = null;
                    }

                    this.moveZombie(zombie, udpConnection3, isoPlayer0);
                }
            }
        }
    }

    public void moveZombie(IsoZombie zombie, UdpConnection to, IsoPlayer player) {
        if (zombie.isDead()) {
            if (zombie.authOwner == null && zombie.authOwnerPlayer == null) {
                zombie.becomeCorpse();
            } else {
                synchronized (this.owns.lock) {
                    zombie.authOwner = null;
                    zombie.authOwnerPlayer = null;
                    zombie.getNetworkCharacterAI().resetSpeedLimiter();
                }

                NetworkZombiePacker.getInstance().setExtraUpdate();
            }

            if (Core.bDebug) {
                DebugLog.log(
                    DebugType.Ownership,
                    String.format("Zombie (%d) owner (\"%s\" / null): zombie is dead", zombie.getOnlineID(), player == null ? "" : player.getUsername())
                );
            }
        } else {
            if (player != null
                && player.getVehicle() != null
                && player.getVehicle().getSpeed2D() > 2.0F
                && player.getVehicle().getDriver() != player
                && player.getVehicle().getDriver() instanceof IsoPlayer) {
                player = (IsoPlayer)player.getVehicle().getDriver();
                to = GameServer.getConnectionFromPlayer(player);
                if (Core.bDebug) {
                    DebugLog.log(
                        DebugType.Ownership,
                        String.format("Zombie (%d) owner (\"%s\"): zombie owner is driver", zombie.getOnlineID(), player == null ? "" : player.getUsername())
                    );
                }
            }

            if (zombie.authOwner != to) {
                synchronized (this.owns.lock) {
                    if (zombie.authOwner != null) {
                        NetworkZombieList.NetworkZombie networkZombie0 = this.owns.getNetworkZombie(zombie.authOwner);
                        if (networkZombie0 != null && !networkZombie0.zombies.remove(zombie)) {
                            DebugLog.log("moveZombie: There are no zombies in nz.zombies.");
                        }
                    }

                    if (to != null) {
                        NetworkZombieList.NetworkZombie networkZombie1 = this.owns.getNetworkZombie(to);
                        if (networkZombie1 != null) {
                            networkZombie1.zombies.add(zombie);
                            zombie.authOwner = to;
                            zombie.authOwnerPlayer = player;
                            zombie.getNetworkCharacterAI().resetSpeedLimiter();
                            to.timerSendZombie.reset(0L);
                        }
                    } else {
                        zombie.authOwner = null;
                        zombie.authOwnerPlayer = null;
                        zombie.getNetworkCharacterAI().resetSpeedLimiter();
                    }
                }

                zombie.lastChangeOwner = System.currentTimeMillis();
                NetworkZombiePacker.getInstance().setExtraUpdate();
            }
        }
    }

    public void getZombieAuth(UdpConnection connection, ByteBuffer bb) {
        NetworkZombieList.NetworkZombie networkZombie = this.owns.getNetworkZombie(connection);
        int int0 = networkZombie.zombies.size();
        int int1 = 0;
        int int2 = bb.position();
        bb.putShort((short)int0);
        synchronized (this.owns.lock) {
            networkZombie.zombies.removeIf(isoZombiex -> isoZombiex.OnlineID == -1);

            for (IsoZombie isoZombie : networkZombie.zombies) {
                if (isoZombie.OnlineID != -1) {
                    bb.putShort(isoZombie.OnlineID);
                    int1++;
                } else {
                    DebugLog.General.error("getZombieAuth: zombie.OnlineID == -1");
                }
            }
        }

        if (int1 < int0) {
            int int3 = bb.position();
            bb.position(int2);
            bb.putShort((short)int1);
            bb.position(int3);
        }
    }

    public LinkedList<IsoZombie> getZombieList(UdpConnection connection) {
        NetworkZombieList.NetworkZombie networkZombie = this.owns.getNetworkZombie(connection);
        return networkZombie.zombies;
    }

    public void clearTargetAuth(UdpConnection connection, IsoPlayer player) {
        if (Core.bDebug) {
            DebugLog.log(DebugType.Multiplayer, "Clear zombies target and auth for player id=" + player.getOnlineID());
        }

        if (GameServer.bServer) {
            for (IsoZombie isoZombie : IsoWorld.instance.CurrentCell.getZombieList()) {
                if (isoZombie.target == player) {
                    isoZombie.setTarget(null);
                }

                if (isoZombie.authOwner == connection) {
                    isoZombie.authOwner = null;
                    isoZombie.authOwnerPlayer = null;
                    isoZombie.getNetworkCharacterAI().resetSpeedLimiter();
                    getInstance().updateAuth(isoZombie);
                }
            }
        }
    }

    public static void removeZombies(UdpConnection connection) {
        int int0 = (IsoChunkMap.ChunkGridWidth / 2 + 2) * 10;

        for (IsoPlayer isoPlayer : connection.players) {
            if (isoPlayer != null) {
                int int1 = (int)isoPlayer.getX();
                int int2 = (int)isoPlayer.getY();

                for (int int3 = 0; int3 < 8; int3++) {
                    for (int int4 = int2 - int0; int4 <= int2 + int0; int4++) {
                        for (int int5 = int1 - int0; int5 <= int1 + int0; int5++) {
                            IsoGridSquare isoGridSquare = IsoWorld.instance.CurrentCell.getGridSquare(int5, int4, int3);
                            if (isoGridSquare != null && !isoGridSquare.getMovingObjects().isEmpty()) {
                                for (int int6 = isoGridSquare.getMovingObjects().size() - 1; int6 >= 0; int6--) {
                                    IsoZombie isoZombie = Type.tryCastTo((IsoMovingObject)isoGridSquare.getMovingObjects().get(int6), IsoZombie.class);
                                    if (isoZombie != null) {
                                        NetworkZombiePacker.getInstance().deleteZombie(isoZombie);
                                        isoZombie.removeFromWorld();
                                        isoZombie.removeFromSquare();
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    public void recheck(UdpConnection connection) {
        synchronized (this.owns.lock) {
            NetworkZombieList.NetworkZombie networkZombie = this.owns.getNetworkZombie(connection);
            if (networkZombie != null) {
                networkZombie.zombies.removeIf(isoZombie -> isoZombie.authOwner != connection);
            }
        }
    }
}
